﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Facebook.Schema;
using System.Web;
using Facebook.Session;
using Facebook.Rest;
using System.Xml;
using Logic;

namespace Social.Facebook
{
	public class FacebookRest 
	{
		public string UserID
		{
            get { return HttpContext.Current.Request.Cookies["FB_Uid"] == null ? "" : HttpContext.Current.Request.Cookies["FB_Uid"].Value; }
		}

		public void AccessTokenGet()
		{
		}

		public string ApplicationKey { get; set; }

		public FacebookSession fbSession;

		public bool IsConnected()
		{
			return (fbSession is ConnectSession && ((ConnectSession)fbSession).IsConnected()) ||
				   (fbSession is DesktopSession && !String.IsNullOrEmpty((fbSession).SessionKey) && !String.IsNullOrEmpty((fbSession).SessionSecret));
		}

		// for web applications (i am only using it for setting application data for applicatons created via oyr application) //
		public FacebookRest(string applicationKey, string secretKey)
		{
			fbSession = new ConnectSession(applicationKey, secretKey);

			this.ApplicationKey = applicationKey;
		}

		// for desktop applications //
		public FacebookRest(string applicationKey, string sessionKey, string sessionSecret)
		{
			fbSession = new DesktopSession(applicationKey, sessionSecret, sessionKey);

			this.ApplicationKey = applicationKey;
		}

		public FacebookRest(string applicationKey)
		{
			this.ApplicationKey = applicationKey;
			if (HttpContext.Current.Request.Cookies["FB_UserSecret"] != null && HttpContext.Current.Request.Cookies["FB_SessionKey"] != null)
				this.fbSession = new DesktopSession(applicationKey, HttpContext.Current.Request.Cookies["FB_UserSecret"].Value, HttpContext.Current.Request.Cookies["FB_SessionKey"].Value);
			else this.fbSession = new DesktopSession(applicationKey, false);
		}

		private IFacebookConfig config;

		public FacebookRest(IFacebookConfig config)
		{
			this.config = config;
			if (!string.IsNullOrEmpty(config.UserSecret) && !string.IsNullOrEmpty(config.SessionKey))
				fbSession = new DesktopSession(config.AppKey, config.UserSecret, config.SessionKey);
			else
				fbSession = new DesktopSession(config.AppKey, false);
		}

		public void PostText(string text)
		{
			try
			{
				var api = new Api(fbSession);
				api.Users.SetStatus(text);
			}
			catch
			{

			}
		}

		public Api Rest
		{
			get { return new Api(fbSession);}
		}

		public user GetUserProfile(string uid)
		{
			try
			{
				var api = new Api(fbSession);
				var user = api.Users.GetInfo(Convert.ToInt64(uid));
				return user;
			}
			catch(Exception)
			{
				return null;
			}

		}

		public string GetEmail()
		{
			string query = string.Format("SELECT email FROM user WHERE uid='{0}'", this.UserID);
			var api = new Api(fbSession);
			string res = api.Fql.Query(query);
			XmlDocument xdoc = new XmlDocument();
			xdoc.LoadXml(res);
			if (xdoc["fql_query_response"] != null && xdoc["fql_query_response"]["user"] != null && xdoc["fql_query_response"]["user"]["email"] != null)
				return xdoc["fql_query_response"]["user"]["email"].InnerText;
			else return "";
		}

		public string GetToolBarID()
		{
			return HttpContext.Current.Request.QueryString["ToolbarID"];
		}

		public class FacebookInterfaceResult
		{
			public string Uid { get; set; }
			public string SessionKey { get; set; }
			public string Expires { get; set; }
			public string UserSecret { get; set; }
			public string Sig { get; set; }

			private const string SESSION_EXPIRY_EXCEPTION_MESSAGE = "session key invalid";

			public bool IsSuccsess { get; set; }
			public bool IsSessionValid { get; set; }
			public string Message { get; set; }

			public FacebookInterfaceResult()
			{
				//unless there is an exception indicating that the session has expired - we assume it is valid
				IsSessionValid = true;
			}
			public FacebookInterfaceResult(bool isSessionValid)
			{
				IsSessionValid = isSessionValid;
				IsSuccsess = false;
			}

			public static void SetExceptionReson(FacebookInterfaceResult result, Exception ex)
			{
				result.IsSuccsess = false;
				result.Message = ex.Message;
				if (ex.Message.ToLower().StartsWith(SESSION_EXPIRY_EXCEPTION_MESSAGE))
					result.IsSessionValid = false;
			}
		}
		//public class ProfileResult : FacebookInterfaceResult
		//{
		//    public facebook.Schema.user UserProfile { get; set; }
		//}
		//public class FriendInfoResult : FacebookInterfaceResult
		//{
		//    public IList<facebook.Schema.user> Friends { get; set; }
		//}
		public class PermissionCheckResult : FacebookInterfaceResult
		{
			public bool IsOfflineAccessGranted { get; set; }
			public bool IsPublishStramGranted { get; set; }
		}

		/// <summary>
		/// Gets the facebook user's profile and populates the BO.User with all relevant information. Stores the user's facebook profile image, if exists, on the server places the new ImageUrl in the BO.User's property.
		/// </summary>
		/// <param name="user">The BO.User to populate. this can be a new or en existing user</param>
		/// <param name="fbUserID">The facebook user ID</param>
		/// <param name="fbSessionKey">The facebook user SessionKey</param>
		/// <param name="fbSecretKey">The facebook user SecretKey</param>
		/// <param name="serverUrl">The URL of the current server on which the profile image will be saved.</param>

		public void logout(System.Web.UI.Page Page)
		{
			System.Web.UI.HtmlControls.HtmlGenericControl iframe = new System.Web.UI.HtmlControls.HtmlGenericControl("iframe");
			iframe.Style["display"] = "none";
			iframe.Attributes["src"] = string.Format("http://www.facebook.com/logout.php?app_key={0}&session_key={1}&next={2}", this.ApplicationKey, this.fbSession.SessionKey, "cnn.com");
			Page.Controls.Add(iframe);
			
			
			//HttpContext.Current.Response.Redirect(string.Format("http://www.facebook.com/logout.php?app_key={0}&session_key={1}&next={2}", this.ApplicationKey, this.fbSession.SessionKey, "cnn.com"));
			//var api = new Facebook.Rest.Api(fbSession);
			//api.Auth.ExpireSession();
			//fbSession.Logout();
			//api.Session.Logout();
			//api.Users.Session.Logout();
			this.DeleteCookies();
		}

		private void DeleteCookies()
		{
			HttpContext.Current.Response.Cookies["FB_Uid"].Expires = DateTime.Now.AddDays(-1);
			HttpContext.Current.Response.Cookies["FB_UserSecret"].Expires = DateTime.Now.AddDays(-1);
			HttpContext.Current.Response.Cookies["FB_SessionKey"].Expires = DateTime.Now.AddDays(-1);
		}

		//public void LoadUser()
		//{
		//    BO.Session session = Sessions.Get().Where(Sessions.Columns.ID, Actions.Equal, HttpContext.Current.Request.Cookies["CommunitySessionID" + GetToolBarID()].Value).SelectOne();
		//    BO.User user;
		//    var fbUser = GetUserProfile(UserID);

		//    if (session.UserID.HasValue)
		//    {
		//        user = BLL.Users.GetByID(session.UserID.Value);
		//        if (user.FaceBookID != fbUser.uid.Value.ToString())
		//        {
		//            user.FaceBookID = fbUser.uid.Value.ToString();
		//            user.TwitterImage = string.IsNullOrEmpty(fbUser.pic_small) ? "http://static.ak.fbcdn.net/pics/q_silhouette.gif" : fbUser.pic_small;
		//            user.FaceBookName = fbUser.name;
		//            user.Update();
		//        }
		//    }
		//    else
		//    {
		//        user = BLL.HelperMethods.CreateUserIfNotExists("FaceBook", fbUser.uid.Value.ToString(), session.ToolBarID, fbUser.name, fbUser.pic_small);
		//        BLL.HelperMethods.SetSession(HttpContext.Current.Request.Cookies["CommunitySessionID" + GetToolBarID()].Value, user.ID);
		//    }
		//}

		public void SetAppData(string callAsAPI, string name, string iconUrl)
		{
			var api = new Api(fbSession);

			api.Permissions.BeginPermissionsMode(callAsAPI);

			api.Admin.SetAppProperties(new Dictionary<string, string> { { "description", name}, 
																			{"callback_url", "http://lehavi.com:2009/" }, 
																			{"application_name",name},
																			{"connect_url","http://lehavi.com:2009/"},
																			{"icon_url",iconUrl}});

			api.Permissions.EndPermissionsMode(callAsAPI);
		}

		public bool IsFollower(long pageID)
		{
			var api = new Api(fbSession);
			return api.Pages.IsFan(pageID);
		}

		// Login

		private const string LoginUrlFormat = "http://www.facebook.com/login.php?api_key={0}&connect_display=popup&v=1.0&next={2}&cancel_url={3}&fbconnect=true&return_session=true&req_perms={1},email"; //,read_stream        
		private const string OfflineAccessPermissionName = "offline_access";
		private const string PublishStreamPermissionName = "publish_stream";

		public string ConnectUrl
		{
			get { return CreateLoginUrl(config.OfflineAccess, config.PublishStream); }
		}

		public string CreateLoginUrl(bool askForOfflineAccess, bool askForPublishStream)
		{
			var permissions = GetPermissions(askForOfflineAccess, askForPublishStream);
			return string.Format(LoginUrlFormat, config.AppKey, permissions, config.LoginSuccessUrl, config.LoginFailUrl);
		}

		private string GetPermissions(bool askForOfflineAccess, bool askForPublishStream)
		{
			var str = new List<string>();
			if (askForOfflineAccess)
				str.Add(OfflineAccessPermissionName);
			if (askForPublishStream)
				str.Add(PublishStreamPermissionName);

			return string.Join(",", str.ToArray());
		}

		public FacebookInterfaceResult ParseSuccesUrl(string url)
		{
			url = Uri.UnescapeDataString(url);

			var result = new FacebookInterfaceResult();

			result.Uid = new Regex(@"(?<=""uid"":"").*?(?="")").Match(url).Value;
			if (string.IsNullOrEmpty(result.Uid))
				result.Uid = new Regex(@"(?<=""uid"":).*?(?=,)").Match(url).Value;
			result.Expires = new Regex(@"(?<=""expires"":).*?(?=,)").Match(url).Value;
			//result.Expires = new Regex(@"(?<=""expires"":"").*?(?="")").Match(url).Value;
			result.UserSecret = new Regex(@"(?<=""secret"":"").*?(?="")").Match(url).Value;
			result.SessionKey = new Regex(@"(?<=""session_key"":"").*?(?="")").Match(url).Value;
			result.Sig = new Regex(@"(?<=""sig"":"").*?(?="")").Match(url).Value;


			return result;
		}

		public void SaveToCookies(FacebookInterfaceResult res)
		{
			HttpContext.Current.Response.Cookies.Add(new HttpCookie("FB_Uid", res.Uid));
			HttpContext.Current.Response.Cookies.Add(new HttpCookie("FB_UserSecret", res.UserSecret));
			HttpContext.Current.Response.Cookies.Add(new HttpCookie("FB_SessionKey", res.SessionKey));
		}

		public void Authenticate()
		{
			var par = ParseSuccesUrl(HttpContext.Current.Request.Url.ToString());
			if (!string.IsNullOrEmpty(par.Uid))
			{
				SaveToCookies(par);
			}
		}
	}
}
